package com.depth.viewer.widget.template
{
	import com.depth.viewer.component.TitlebarButton;
	import com.depth.viewer.container.IWidgetContainer;
	import com.depth.viewer.container.ViewerContainer;
	import com.depth.viewer.events.AppEvent;
	import com.depth.viewer.facade.IocAppFacade;
	import com.depth.viewer.manager.ViewerSystemManager;
	import com.depth.viewer.widget.BaseWidget;
	import com.depth.viewer.widget.IBaseWidget;
	import com.depth.viewer.widget.IFocusWidget;
	import com.depth.viewer.widget.WidgetStates;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.utils.setTimeout;
	
	import mx.controls.Image;
	import mx.core.DragSource;
	import mx.core.FlexGlobals;
	import mx.core.FlexTextField;
	import mx.core.UIComponent;
	import mx.events.FlexEvent;
	import mx.events.PropertyChangeEvent;
	import mx.events.PropertyChangeEventKind;
	import mx.managers.CursorManager;
	import mx.managers.DragManager;
	
	import spark.components.Application;
	import spark.components.Group;
	import spark.components.Label;
	import spark.components.SkinnableContainer;
	
	
	[Event(name="opened", type="flash.events.Event")]
	[Event(name="minimized", type="flash.events.Event")]
	[Event(name="closed", type="flash.events.Event")]
	
	[SkinState("opened")]
	[SkinState("minimized")]
	[SkinState("closed")]
	
	[Style(name="minimizeIcon",type="String")]
	[Style(name="closeIcon",type="String")]
	[Style(name="resizeIcon",type="String")]
	
	[Bindable]
	public class WidgetTemplate extends SkinnableContainer implements IWidgetTemplate
	{
		[SkinPart(required="false")]
		public var widgetFrame:Group;
		
		[SkinPart(required="false")]
		public var header:Group;
		
		[SkinPart(required="false")]
		public var headerToolGroup:Group;
		
		[SkinPart(required="false")]
		public var icon:Image;
		
		[SkinPart(required="false")]
		public var labelIcon:Image;
		
		[SkinPart(required="false")]
		public var closeButton:Image;
		
		[SkinPart(required="false")]
		public var minimizeButton:Image;
		
		[SkinPart(required="false")]
		public var maximizeButton:Image;
		
		[SkinPart(required="false")]
		public var resizeButton:Image;
		
		[SkinPart(required="false")]
		public var widgetLabel:Label;
		
		[Bindable]
		public var enableCloseButton:Boolean = true;
		
		[Bindable]
		public var enableMinimizeButton:Boolean = true;
		
		[Bindable]
		public var enableResizeButton:Boolean = true;
		
		[Bindable]
		public var enableDraging:Boolean = true;
		
		
		
		[Embed(source="assets/images/w_resizecursor.png")]
		public var resizeCursor:Class;
		
		[embed(source="assets/images/w_drag.png")]
		public var dragCursor:Class;
		
		[Bindable]
		public var contentClipAndEnableScrolling:Boolean = true;
		
		
		[Bindable]
		public var enableIcon:Boolean = true;
		
		public var closeHandler:Function;
		
		[Bindable]
		private var _widgetId:String;
		[Bindable]
		private var _widgetState:String = WidgetStates.WIDGET_OPENED;
		[Bindable]
		private var _cursorID:int = 0;
		[Bindable]
		private var _widgetTitle:String = "";
		[Bindable]
		private var _widgetIcon:String = "";
		[Bindable]
		private var _widgetLabelIcon:String = "";
		[Bindable]
		private var _draggable:Boolean = true;
		[Bindable]
		private var _dragDropable:Boolean = false;
		[Bindable]
		private var _resizable:Boolean = false;
		[Bindable]
		private var _closeable:Boolean = true;
		[Bindable]
		private var _minimizeable:Boolean = true;
		
		private var _baseWidget:IBaseWidget;
		
		
		private var _widgetWidth:Number;
		[Bindable]
		public function set widgetWidth(value:Number):void
		{
			_widgetWidth = value;
			dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE,true,true,PropertyChangeEventKind.UPDATE,widgetWidth,null,_widgetHeight,this));
		}
		
		public function get widgetWidth():Number{
			return _widgetWidth;
		}
		
		
		private var _widgetHeight:Number;
		
		[Bindable]
		public function set widgetHeight(value:Number):void
		{
			_widgetHeight = value;
			dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE,true,true,PropertyChangeEventKind.UPDATE,widgetHeight,null,_widgetHeight,this));
		}
		
		
		public function get widgetHeight():Number{
			return _widgetHeight;
		}
		
		[Bindable]
		public var bottomMessage:String;
		
		
		public function set baseWidget(value:IBaseWidget):void
		{
			_baseWidget = value;
			
			widgetState = value.getState();
			
			BaseWidget(value).widgetTemplates.push(this);
			/* this.resizable = value.isResizeable;
			this.draggable = value.isDraggable;
			this.widgetId = value.widgetId;
			this.widgetTitle = value.widgetTitle;
			this.widgetIcon = value.widgetIcon;
			this.dragDropable = value.isDragDropable;*/
		}
		public function set title(value:String):void{
			this.widgetTitle = value;
		}
		
		public function get baseWidget():IBaseWidget
		{
			return _baseWidget?_baseWidget:parent as IBaseWidget;
		}
		/*	override public function set width(value:Number):void{
		value += 40;
		super.width = value;
		_widgetWidth = value;
		}
		override public function set height(value:Number):void{
		value += 55;
		super.height = value;
		_widgetHeight = value;
		}*/
		private var _contentWidthFag:Boolean;
		private var _contentHeightFag:Boolean;
		public function set contentWidth(value:Number):void{
			_contentWidthFag = true;
			widgetWidth = value;
			invalidateProperties();
		}
		public function set contentHeight(value:Number):void{
			_contentHeightFag = true;
			widgetHeight = value;
			invalidateProperties();
		}
		
		public function set resizable(value:Boolean):void
		{
			if (enableResizeButton)
			{
				_resizable = value;
			}
		}
		[Bindable]
		public function get resizable():Boolean
		{
			return _resizable;
		}
		public function get closeable():Boolean{
			return _closeable;	
		}
		public function set closeable(value:Boolean):void{
			this._closeable = value;
			
			invalidateProperties();
		}
		public function get minimizeable():Boolean{
			return _minimizeable;	
		}
		public function set minimizeable(value:Boolean):void{
			this._minimizeable = value;
		}
		public function set draggable(value:Boolean):void
		{
			if (enableDraging)
			{
				_draggable = value;
			}
			else
			{
				_draggable = false;
			}
		}
		public function set dragDropable(value:Boolean):void{
			this._dragDropable = value;
		}
		public function get widgetId():String
		{
			return _widgetId;
		}
		
		public function set widgetId(value:String):void
		{
			_widgetId = value;
		}
		
		[Bindable]
		public function get widgetTitle():String
		{
			return _widgetTitle;
		}
		
		public function set widgetTitle(value:String):void
		{
			_widgetTitle = value;
			if(widgetLabel){
				widgetLabel.text = _widgetTitle;
			}
		}
		
		[Bindable]
		public function get widgetLabelIcon():String{
			return this._widgetLabelIcon;
		}
		public function set widgetLabelIcon(value:String):void{
			this._widgetLabelIcon = value;
		}
		
		[Bindable]
		public function get widgetIcon():String
		{
			return _widgetIcon;
		}
		
		public function set widgetIcon(value:String):void
		{
			_widgetIcon = value;
		}
		
		private var _widgetStateFag:Boolean = false;
		public function set widgetState(value:String):void
		{
			if(_widgetState != value){
				this.widgetFrame.toolTip = "";
				this.icon.toolTip = "";
				
				_widgetState = value;
				_widgetStateFag = true;
				
				if (_widgetState == WidgetStates.WIDGET_MINIMIZED)
				{
					this.widgetFrame.toolTip = this.widgetTitle;
					this.icon.toolTip = this.widgetTitle;
				}
				invalidateSkinState();
				invalidateProperties();
			}
		}
		
		public function get widgetState():String
		{
			return _widgetState;
		}
		
		
		public function isRtl():Boolean
		{
			var result:Boolean = false;
			try
			{
				result = (FlexGlobals.topLevelApplication as Application).layoutDirection == "rtl";
			}
			catch (error:Error)
			{
				result = false;
			}
			return result;
		}
		
		private var _selectedTitlebarButtonIndex:int = -1;
		private var _selectedTitlebarButtonIndexChanged:Boolean = false;
		
		public function get selectedTitlebarButtonIndex():int
		{
			return _selectedTitlebarButtonIndex;
		}
		
		public function set selectedTitlebarButtonIndex(value:int):void
		{
			if (_selectedTitlebarButtonIndex != value)
			{
				_selectedTitlebarButtonIndex = value;
				_selectedTitlebarButtonIndexChanged = true;
				invalidateProperties();
			}
		}
		
		public function WidgetTemplate()
		{
			super();
			
			this.addEventListener(FlexEvent.CREATION_COMPLETE, creationCompleteHandler);
			ViewerContainer.addEventListener(AppEvent.WIDGET_CLOSED,closeEventHnalder);
		}
		
		private function creationCompleteHandler(event:Event):void
		{
			if(closeButton)
				this.closeButton.toolTip = "关闭";
			if(minimizeButton)
				this.minimizeButton.toolTip = "最小化";
			
			dispatchEvent(new Event("opened"));
		}
		
		protected override function partAdded(partName:String, instance:Object):void
		{
			super.partAdded(partName, instance);
			if (instance == icon)
			{
				icon.toolTip = "按下鼠标拖动可以拖出容器，拖拽到任何位置，也可以用同样的方式拖回此容器进行自动布局";
				icon.addEventListener(MouseEvent.CLICK, icon_clickHandler);
				icon.addEventListener(MouseEvent.MOUSE_DOWN,icon_downHandler);
			}
			if (instance == widgetFrame)
			{
				// widgetFrame.addEventListener(MouseEvent.MOUSE_DOWN, mouse_downHandler);
				// widgetFrame.addEventListener(MouseEvent.MOUSE_UP, mouse_upHandler);
				
				// widgetFrame.stage.addEventListener(MouseEvent.MOUSE_UP, mouse_upHandler);
				widgetFrame.stage.addEventListener(Event.MOUSE_LEAVE, stageout_Handler);
			}
			if (instance == header)
			{
				header.addEventListener(MouseEvent.MOUSE_DOWN, mouse_downHandler);
			}
			if (instance == closeButton)
			{
				closeButton.addEventListener(MouseEvent.CLICK, close_clickHandler);
				if(closeable){
					closeButton.visible = true;
				}else{
					closeButton.visible = false;
				}
			}
			if (instance == minimizeButton)
			{
				minimizeButton.addEventListener(MouseEvent.CLICK, minimize_clickHandler);
				if(minimizeable){
					minimizeButton.visible = true;
				}else{
					minimizeButton.visible = false;
				}
			}
			if (instance == resizeButton)
			{
				resizeButton.addEventListener(MouseEvent.MOUSE_OVER, resize_overHandler);
				resizeButton.addEventListener(MouseEvent.MOUSE_OUT, resize_outHandler);
				resizeButton.addEventListener(MouseEvent.MOUSE_DOWN, resize_downHandler);
				if(resizable){
					resizeButton.visible = true;
				}else{
					resizeButton.visible = false;
				}
			}
			if(instance == widgetFrame){
				widgetFrame.addEventListener(MouseEvent.CLICK,wFrameClickHandler);
			}
			if(instance == widgetLabel){
				widgetLabel.text = _widgetTitle;
			}
			if(instance == labelIcon){
				labelIcon.addEventListener(MouseEvent.CLICK,widgetLabelClickHandler);
			}
			if(instance == maximizeButton){
				maximizeButton.addEventListener(MouseEvent.CLICK,maximize_clickHandler);
			}
		}
		
		override protected function getCurrentSkinState():String
		{
			return _widgetState;
		}
		
		override protected function commitProperties():void
		{
			super.commitProperties();
			
			if(_contentWidthFag){
				var contentPaddingLeft:Number = getStyle("contentPaddingLeft");
				var contentPaddingRight:Number = getStyle("contentPaddingRight");
				
				if(isNaN(contentPaddingLeft) || isNaN(contentPaddingRight)){
					invalidateProperties();
				}else{
					
					_widgetWidth += (contentPaddingLeft + contentPaddingRight);
					
					width = _widgetWidth;
					
					_contentWidthFag = false;
				}
			}
			
			if(_contentHeightFag){
				var contentPaddingTop:Number = getStyle("contentPaddingTop");
				var contentPaddingBottom:Number = getStyle("contentPaddingBottom");
				
				if(isNaN(contentPaddingTop) || isNaN(contentPaddingBottom)){
					invalidateProperties();
				}else{
					
					widgetHeight += (contentPaddingTop + contentPaddingBottom);
					
					height = widgetHeight;
					
					_contentHeightFag = false;
				}
			}
			
			if (_selectedTitlebarButtonIndexChanged)
			{
				_selectedTitlebarButtonIndexChanged = false;
				for (var i:int = 0, n:int = headerToolGroup.numElements; i < n; i++)
				{
					var btn:TitlebarButton = TitlebarButton(headerToolGroup.getElementAt(i));
					if (i == _selectedTitlebarButtonIndex)
					{
						btn.selected = true;
					}
					else
					{
						btn.selected = false;
					}
				}
			}
			if(_widgetStateFag){
				/*if(_widgetState == WidgetStates.WIDGET_MINIMIZED){
				this.height = 30;
				this.width = 250;
				}
				if(_widgetState == WidgetStates.WIDGET_OPENED){
				this.width = _widgetWidth;
				this.height = _widgetHeight;
				}*/
			}
			if(closeButton)
				closeButton.visible = closeable;
		}
		
		private function mouse_downHandler(event:MouseEvent):void
		{
			if (_draggable && enableDraging)
			{
				header.addEventListener(MouseEvent.MOUSE_MOVE, mouse_moveHandler);
				stage.addEventListener(MouseEvent.MOUSE_UP, mouse_upHandler);			
			}
		}
		
		private function wFrameClickHandler(event:MouseEvent):void{
			if(baseWidget && baseWidget.container){
				baseWidget.container.focusWidget(baseWidget.widgetId);
			}
		}
		
		private function widgetLabelClickHandler(event:MouseEvent):void{
			if(widgetState == WidgetStates.WIDGET_MINIMIZED){
				widgetState = WidgetStates.WIDGET_OPENED;
				setBaseWidgetState();
			}
		}
		
		private function setBaseWidgetState():void{
			if(baseWidget && baseWidget.widgetId)
				baseWidget.setState(widgetState);
		}
		
		private var widgetMoveStarted:Boolean = false;
		
		private function mouse_moveHandler(event:MouseEvent):void
		{
			if (!widgetMoveStarted)
			{
				widgetMoveStarted = true;
				
				//TODO: not for V2.0
				//ViewerContainer.dispatchEvent(new AppEvent(AppEvent.CHANGE_LAYOUT, LAYOUT_BASIC));
				
				this.alpha = 0.7;
				var widget:UIComponent = baseWidget as UIComponent;
				
				if (!DragManager.isDragging)
				{
					var rect:Rectangle = new Rectangle(0,0,BaseWidget(baseWidget).parent.width - 260,BaseWidget(baseWidget).parent.height - 60)
					widget.startDrag(false,rect);
				}
				
				if (_resizable)
				{
					ViewerContainer.dispatchEvent(new AppEvent(AppEvent.WIDGET_FOCUS_IN, widgetId));
				}
			}
		}
		
		private function mouse_upHandler(event:MouseEvent):void
		{
			if (_draggable && enableDraging){
				header.removeEventListener(MouseEvent.MOUSE_MOVE, mouse_moveHandler);
				if(stage)
					stage.removeEventListener(MouseEvent.MOUSE_UP, mouse_upHandler);
				
				this.alpha = 1;
				
				var widget:UIComponent = baseWidget as UIComponent;
				
				widget.stopDrag();
				
				
				relativePositioning();
				
				widgetMoveStarted = false;
			}
			
			
			//CursorManager.removeCursor(CursorManager.currentCursorID);
		}
		
		private function stageout_Handler(event:Event):void
		{
			if (widgetMoveStarted)
			{
				mouse_upHandler(null);
			}
		}
		
		private function notifyStateChanged(widgetState:String):void
		{
			var data:Object =
				{
					id: _widgetId,
					icon:_widgetIcon,
					lable:_widgetTitle,
					state: widgetState
				};
			ViewerContainer.dispatchEvent(new AppEvent(AppEvent.WIDGET_STATE_CHANGED, data));
			
		}
		
		protected function icon_clickHandler(event:MouseEvent):void
		{
			
			widgetState = WidgetStates.WIDGET_OPENED;
			setBaseWidgetState();
			//dispatchEvent(new Event(WIDGET_OPENED));
			
			this.widgetFrame.toolTip = "";
			this.icon.toolTip = "";
			
			notifyStateChanged(WidgetStates.WIDGET_OPENED);
		}
		protected function icon_downHandler(event:MouseEvent):void{
			if(!this.baseWidget) return;
			if(_dragDropable && widgetState == WidgetStates.WIDGET_OPENED){
				var initiator:BaseWidget = this.baseWidget as BaseWidget;
				var dragSource:DragSource=new DragSource();   
				
				dragSource.addData(initiator,BaseWidget.DROP_FOMAT);   
				
				var bitmapData:BitmapData = new BitmapData(width,height);
				bitmapData.draw(initiator);
				var bitmap:Bitmap = new Bitmap(bitmapData);
				var proxyImg:Image = new Image();
				proxyImg.source = bitmap;
				
				DragManager.doDrag(initiator,dragSource,event,proxyImg); 
			}
		}
		protected function closeEventHnalder(e:AppEvent):void{
			if(baseWidget == e.data)
				close();
		}
		protected function close_clickHandler(event:MouseEvent = null):void
		{
			
			//close();
			widgetState = WidgetStates.WIDGET_CLOSED;
			
			setBaseWidgetState();
			
			invalidateSkinState();
			notifyStateChanged(WidgetStates.WIDGET_CLOSED);	
		}
		public function close():void{
			var baseWidget:IBaseWidget = baseWidget as IBaseWidget;
			if(baseWidget){
				setTimeout(function(){
					IocAppFacade.getInstance().sendNotification(IocAppFacade.REMOVE_WIDGET,baseWidget.widgetId);
				},200);
			}
			
			if(closeHandler){
				closeHandler();
			}
		}
		protected function maximize_clickHandler(event:MouseEvent):void{
			if(widgetState == WidgetStates.WIDGET_MINIMIZED){
				widgetState = WidgetStates.WIDGET_OPENED;
				setBaseWidgetState();
			}
		}
		protected function minimize_clickHandler(event:MouseEvent):void
		{
			widgetState = WidgetStates.WIDGET_MINIMIZED;
			//dispatchEvent(new Event(WIDGET_MINIMIZED));
			setBaseWidgetState();
			
			widgetFrame.toolTip = this.widgetTitle;
			icon.toolTip = this.widgetTitle;
			
			notifyStateChanged(WidgetStates.WIDGET_MINIMIZED);
			
		}
		
		private function resize_overHandler(event:MouseEvent):void
		{
			_cursorID = CursorManager.setCursor(resizeCursor, 2, -10, -10);
		}
		
		private function resize_outHandler(event:MouseEvent):void
		{
			CursorManager.removeCursor(_cursorID);
		}
		
		private function resize_downHandler(event:MouseEvent):void
		{
			if (_resizable && this.enableResizeButton)
			{
				/*TODO: for now, it can't be resized when is not basic layout*/
				stage.addEventListener(MouseEvent.MOUSE_MOVE, resize_moveHandler);
				stage.addEventListener(MouseEvent.MOUSE_UP, resize_upHandler);
				
				/*var widget:UIComponent = parent as UIComponent;
				if(widget){
				widget.right = undefined;
				widget.bottom = undefined;
				widget.left = widget.x;
				widget.top = widget.y;
				}*/
			}
		}
		
		private function resize_moveHandler(event:MouseEvent):void
		{
			// if there is minWidth and minHeight specified on the container, use them while resizing
			const minimumResizeWidth:Number = minWidth ? minWidth : 200;
			const minimumResizeHeight:Number = minHeight ? minHeight : 100;
			
			
			if (mouseX  > minimumResizeWidth)
			{
				width = mouseX;
			}
			if (mouseY > minimumResizeHeight)
			{
				height = mouseY;
			}
		}
		
		private function resize_upHandler(event:MouseEvent):void
		{
			
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, resize_moveHandler);
			stage.removeEventListener(MouseEvent.MOUSE_UP, resize_upHandler);
			
			
			
			widgetHeight = height;
			widgetWidth =  width;
		}
		private function relativePositioning():void{
			/*var widget:UIComponent = parent as UIComponent;
			if(!widget)
			return;
			widget.left = undefined;
			widget.right = undefined;
			widget.top = undefined;
			widget.bottom = undefined;
			if(widget.x + widget.width/2 >= BaseWidget(baseWidget).parent.width/2){
			widget.right = (BaseWidget(baseWidget).parent.width - (widget.x + widget.width));
			}else{
			widget.left = widget.x;
			}
			if(widget.y + widget.height/2 >= BaseWidget(baseWidget).parent.height/2){
			widget.bottom = BaseWidget(baseWidget).parent.height - (widget.y + widget.height);
			}else{
			widget.top = widget.y;
			}*/
			
			/*if(widget.x < 0 ){
			widget.left = 0;
			widget.stopDrag();
			}
			if(widget.y < 0){
			widget.top = 0;		
			widget.stopDrag();
			}
			if(widget.x + widget.width > FlexGlobals.topLevelApplication.width){
			widget.right = 0;
			widget.stopDrag();
			}
			if(widget.y + widget.height > FlexGlobals.topLevelApplication.height){
			widget.bottom = 0;
			widget.stopDrag();
			}
			*/
			var widget:UIComponent = baseWidget as UIComponent;
			if(!widget)
				return;
			widget.left = undefined;
			widget.right = undefined;
			widget.top = undefined;
			widget.bottom = undefined;
		}
		public function addTitlebarButton(btnIcon:String, btnTip:String, btnFunction:Function, selectable:Boolean = true):void
		{
			var btn:TitlebarButton = new TitlebarButton();
			btn.callback = btnFunction;
			btn.selectable = selectable;
			btn.source = btnIcon;
			btn.toolTip = btnTip;
			
			if (selectable)
			{
				btn.addEventListener(MouseEvent.CLICK, titlebarButton_clickHandler);
				if (headerToolGroup.numElements == 0)
				{
					selectedTitlebarButtonIndex = 0; // automatically select the first button added
				}
			}
			
			headerToolGroup.addElement(btn);
		}
		
		private function titlebarButton_clickHandler(event:MouseEvent):void
		{
			selectedTitlebarButtonIndex = headerToolGroup.getElementIndex(TitlebarButton(event.currentTarget));
		}
	}
	
}
